package com.zhanghe.study.thread.aqs;

import java.util.UUID;
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author zh
 * @date 2022/1/5 17:11
 */
public class TestSemaphore {

    public static void main(String[] args) {
        UseSemaphore useSemaphore = new UseSemaphore();

        for(int i = 0; i< 60;i++){
            ThreadP threadP = new ThreadP(useSemaphore);
            threadP.start();
        }

        for(int i = 0; i< 60;i++){
            ThreadC threadC = new ThreadC(useSemaphore);
            threadC.start();
        }
    }

    // 生产者线程
    static class ThreadP extends Thread{

        UseSemaphore useSemaphore;
        public ThreadP(UseSemaphore useSemaphore){
            super();
            this.useSemaphore = useSemaphore;
        }

        @Override
        public void run() {
            useSemaphore.put();
        }
    }
    // 消费者线程
    static class ThreadC extends Thread{

        UseSemaphore useSemaphore;
        public ThreadC(UseSemaphore useSemaphore){
            super();
            this.useSemaphore = useSemaphore;
        }
        @Override
        public void run() {
            useSemaphore.poll();
        }
    }

    static class UseSemaphore{
        private volatile Semaphore consumerSemaphore = new Semaphore(20); // 消费者
        private volatile Semaphore producerSemaphore = new Semaphore(5); // 生产者

        private volatile ReentrantLock lock = new ReentrantLock();
        private volatile Condition consumerCondition = lock.newCondition();
        private volatile Condition producerCondition = lock.newCondition();

        private volatile Object[] store = new Object[10]; // 可存储的商品数量

        // 是否已空
        private boolean isEmpty(){
            boolean isEmpty = true;
            for(int i = 0;i < store.length;i++){
                if(store[i] != null){
                    isEmpty = false;
                    break;
                }
            }

            return isEmpty;
        }

        // 是否已满
        private boolean isFull(){
            boolean isFull = true;
            for(int i = 0;i < store.length;i++){
                if(store[i] == null){
                    isFull = false;
                    break;
                }
            }

            return isFull;
        }

        // 生产
        public void put(){
            try{
                producerSemaphore.acquire();
                lock.lock();
                while (isFull()){
                    System.out.println("仓库已满，生产者在等待生产");
                    producerCondition.await();
                }

                for(int i = 0;i<store.length;i++){
                    if(store[i] == null){
                        store[i] = "商品"+ UUID.randomUUID().toString();
                        System.out.println(Thread.currentThread().getName() + "生产了"+store[i]);
                        break;
                    }
                }
                consumerCondition.signalAll();
                lock.unlock();
            } catch (InterruptedException e){
                e.printStackTrace();
            } finally {
                producerSemaphore.release();
            }

        }

        // 消费
        public void poll(){
            try{
                consumerSemaphore.acquire();
                lock.lock();
                while (isEmpty()){
                    System.out.println("仓库没货了，消费者在等待商品");
                    consumerCondition.await();
                }

                for(int i = 0;i<store.length;i++){
                    if(store[i] != null){
                        System.out.println(Thread.currentThread().getName()+"消费了商品"+store[i]);
                        store[i] = null;
                        break;
                    }
                }
                producerCondition.signalAll();
                lock.unlock();
            } catch (InterruptedException e){
                e.printStackTrace();
            } finally {
                consumerSemaphore.release();
            }

        }
    }
}
